﻿using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.PlatformAbstractions;
using Sino.CapacityCloud.Infrastructure.Events;
using Sino.CapacityCloud.Repositories.Models;
using Sino.CapacityCloud.Services;
using Sino.Tms.Primitives;
using Sino.TMSystem;
using Sino.WebApi.Framework.Responses;
using System;
using System.Threading.Tasks;

namespace Sino.CapacityCloud.WebApi.ApiControllers
{

    public class CostController
        : ApiController<CostController>
    {

        private readonly ITmsServiceBus _tmsService;
        private readonly IEventBus _eventBus;

        public CostController(
            IHostingEnvironment env,
            IApplicationEnvironment applicationEnvironment,
            IDistributedCache cache,
            ITokenGenertationService tokenGenertationService,
            IEventBus eventBus,
            ApplicationDbContext dbContext,
            ApplicationUserManager userManager,
            ApplicationRoleManager roleManager,
            ApplicationSignInManager signInManager,
            ILoggerFactory loggerFactory,
            ITmsServiceBus tmsService)
            : base(env, applicationEnvironment, cache, tokenGenertationService, dbContext, userManager, roleManager, signInManager, loggerFactory)
        {
            this._eventBus = eventBus;
            this._tmsService = tmsService;
        }

        public async Task<JsonResult> ReturnToTransact(string feeSettleBillId)
        {
            try
            {
                var result = await this._tmsService.ReturnToTransactAsync(feeSettleBillId);
                if (result != null && result.Output != null)
                {
                    if (!string.IsNullOrWhiteSpace(result.Output.ExtData))
                    {
                        return await this.PackageResultAsync<VoidResponse>(new Exception(result.Output.ExtData));
                    }
                    return await this.PackageResultAsync<VoidResponse>();
                }
                throw new InvalidOperationException($"Failed to return to transact step: {nameof(feeSettleBillId)} = {feeSettleBillId}.");
            }
            catch (Exception ex)
            {
                this._logger.LogError($"Failed to return to transact step because: {ex.Message + Environment.NewLine + ex.StackTrace}");
                return await this.PackageResultAsync<VoidResponse>(ex);
            }
        }

        public async Task<JsonResult> StartEbankPayment(string carrierOrderId, string costId, FeeType type, double price, string feeSettleBillCode, string feeSettleBillId)
        {
            try
            {
                var user = await this.UserManager.FindByNameAsync(this.User.Identity.Name);
                if (user != null)
                {
                    var currentTime = DateTime.Now;
                    this.DataContext.PaymentHistories.Add(new PaymentHistory()
                    {
                        CarrierOrderId = carrierOrderId,
                        CostId = costId,
                        Price = price,
                        SettleBillCode = feeSettleBillCode,
                        SettleBillId = feeSettleBillId,
                        LastPaymentTime = currentTime,
                        Type = type,
                        Status = FeeStatus.InPayment,
                        UserId = user.Id,
                    });
                    this.DataContext.SaveChanges();
                    //var result = await this._tmsService.StartEbankPaymentAsync(feeSettleBillId);
                    //if (result?.Output != null)
                    //{
                    //    var response = new PaymentApplicationResultResponse()
                    //    {
                    //        IsSuccess = result.Output.IsPaying,
                    //        ErrorMessage = result.Output.ErrorInfo,
                    //        Status = result.Output.FeeStatus,
                    //        LastPaymentTime = currentTime
                    //    };
                    //    return await this.PackageResultAsync<PaymentApplicationResultResponse>(response);
                    //}
                    //throw new InvalidOperationException($"Failed to start ebank payment: {nameof(feeSettleBillId)} = {feeSettleBillId}.");
                    await Task.Run(() =>
                    {
                        this._eventBus.Post(new PaymentEventData()
                        {
                            FeeSettleBillId = feeSettleBillId
                        }, TimeSpan.Zero);
                    }).ConfigureAwait(false);
                    var response = new PaymentApplicationResultResponse()
                    {
                        IsSuccess = true,
                        ErrorMessage = null,
                        Status = FeeStatus.InPayment,
                        LastPaymentTime = currentTime.AddHours(8)
                    };
                    return await this.PackageResultAsync<PaymentApplicationResultResponse>(response);
                }
                throw new SystemException($"Failed to find the specified ApplicationUser object.");
            }
            catch (Exception ex)
            {
                this._logger.LogError($"Failed to start ebank payment because: {ex.Message + Environment.NewLine + ex.StackTrace}");
                return await this.PackageResultAsync<PaymentApplicationResultResponse>(ex);
            }
        }

    }

}